package cz.matasek.dbLogger.model;

import cz.matasek.dbLogger.Util;
import cz.matasek.dbLogger.sql.SQLDataType;

/**
 * The class represents a column in a database table.
 *
 * @author Luboš Matásek
 */
public class Column implements Comparable<Column> {

    /**
     * Name of the column.
     */
    private String name;
    /**
     * Data type of the column as instance of
     * {@link cz.matasek.dbLogger.sql.SQLDataType}.
     */
    private SQLDataType dataType;
    /**
     * Name of the data type as presented by the particular database platform.
     */
    private String dataTypeName;
    /**
     * <code>true</code> if this column value is logged by the application.
     */
    private boolean isLogged = false;

    /**
     * Creates a new <code>Column</code> with the specified name.
     *
     * @param name name of the column
     */
    public Column(String name) {
        this.name = name.toLowerCase();
        this.dataType = SQLDataType.UNKNOWN;
    }

    /**
     * Creates a new <code>Column</code> with the specified name and data type.
     *
     * @param name name of the column
     * @param dataTypeName name of the data type
     */
    public Column(String name, String dataTypeName) {
        this.name = name.toLowerCase();
        this.dataType = SQLDataType.getType(dataTypeName);
        this.dataTypeName = dataTypeName;
    }

    /**
     * Returns the name of the column.
     *
     * @return the name of the column
     */
    public String getName() {
        return name;
    }

    /**
     * Returns the data type of this column.
     *
     * @return the data type of this column
     */
    public SQLDataType getDataType() {
        return dataType;
    }

    /**
     * Returns the data type name of this column.
     *
     * @return this column's data type name
     */
    public String getDataTypeName() {
        return dataTypeName;
    }

    /**
     * Returns SQL clause defining this column. The definition contains name of
     * the column and its data type.
     *
     * @return SQL clause defining this column
     */
    public final String getSQL() {
        return name + " " + dataTypeName;
    }

    /**
     * Returns the string representation of this column.
     *
     * @return the name of this column
     */
    @Override
    public String toString() {
        return name;
    }

    /**
     * Retrieves if this column is auto-generated by the logging application.
     * Generated columns begins with the logging application prefix (this prefix
     * is common for all logging objects in the database).
     *
     * @param prefix the prefix of all logging objects
     * @return <code>true</code> if this column is auto-generated by the logging
     * application; <code>false</code> otherwise
     */
    public boolean isLoggingColumn(String prefix) {
        return Util.startsWithIgnoreCase(name, prefix);
    }

    /**
     * Compares this column with the specified column for order. Columns are
     * ordered alphabetically according to their names.
     *
     * @param o the column to be compared
     * @return a negative integer, zero, or a positive integer as this column is
     * less than, equal to, or greater than the specified column
     */
    @Override
    public int compareTo(Column o) {
        return name.compareToIgnoreCase(o.name);
    }

    /**
     * Retrieves if changes in this column are logged.
     *
     * @return <code>true</code> if changes are logged; <code>false</code>
     * otherwise
     */
    public boolean isLogged() {
        return isLogged;
    }

    /**
     * Sets if changes in this column are logged.
     *
     * @param isLogged <code>true</code> if changes are logged;
     * <code>false</code> otherwise
     */
    public void setLogged(boolean isLogged) {
        this.isLogged = isLogged;
    }

    /**
     * Indicates whether some other object is "equal to" this column. Object is
     * equal only if:
     * <ul>
     *  <li>it is an instance of the class <code>Column</code></li>
     *  <li>names of both columns are the same</li>
     * </ul>
     *
     * @param o the reference object with which to compare
     * @return <code>true</code> if this object is the same as the obj argument;
     * <code>false</code> otherwise
     */
    @Override
    public boolean equals(Object o) {
        if (o == null || !(o instanceof Column)) {
            return false;
        }

        return name.equalsIgnoreCase(((Column) o).name);
    }

    /**
     * Returns a hash code value for this object.
     *
     * @return hash code value for this object
     */
    @Override
    public int hashCode() {
        int hash = 5;
        return 37 * hash + (name != null ? name.toLowerCase().hashCode() : 0);
    }
}
